package com.moli.iov.alarm.remote.impl;

import com.moli.iov.alarm.model.dto.StatAlarmDTO;
import com.moli.iov.alarm.model.dto.StatAlarmLineDTO;
import com.moli.iov.alarm.model.dto.req.AlarmInfoReqDto;
import com.moli.iov.alarm.model.dto.req.StatAlarmParamDto;
import com.moli.iov.alarm.model.dto.res.AlarmInfoResDto;
import com.moli.iov.alarm.model.dto.res.StatAlarmRatioDTO;
import com.moli.iov.alarm.model.po.StatAlarm;
import com.moli.iov.alarm.remote.IAlarmStatRemoteService;
import com.moli.iov.alarm.service.IAlarmService;
import com.moli.iov.alarm.service.stat.IAlarmStatDetailService;
import com.moli.iov.alarm.service.stat.IAlarmStatService;
import com.moli.iov.handle.alarm.enums.AlarmCodeEnum;
import com.moli.iov.handle.alarm.enums.AlarmLevelEnum;
import com.moli.iov.rest.RestResponse;
import com.moli.iov.util.CommonUtils;
import com.moli.iov.util.DateUtil;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;

import com.moli.iov.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

@Slf4j
@Service(group = "${service.group}")
public class AlarmStatRemoteServiceImpl implements IAlarmStatRemoteService {

    private static Long DAY_TIME = 86400000L;

    private static Long HOUR_TIME = 3600000L;

    private static Long MONTH_TIME = 2592000000L;

    @Resource
    IAlarmStatService alarmStatService;

    @Resource
    IAlarmStatDetailService alarmStatDetailService;

    @Resource
    IAlarmService alarmService;

    @Override
    public RestResponse<StatAlarmDTO> getStatAlarm(Long companyId, Integer statType) {
        if (statType == null) {
            return RestResponse.failure("统计类型不能为空");
        }
        List<StatAlarm> list = alarmStatService.listStatAlarm(companyId, 30 * 2);
        if(list!=null){
            log.info("统计报警:{}",list.size());
        }

        if (CollectionUtils.isEmpty(list)) {
            return RestResponse.success();
        }

        List<StatAlarmLineDTO> statAlarmLineDTOList = new ArrayList<>();
        //同比列表
        List<StatAlarm> oldMonthStatAlarmList = new ArrayList<>();
        List<StatAlarm> newMonthStatAlarmList = new ArrayList<>();

        List<StatAlarm> oldWeekStatAlarmList = new ArrayList<>();
        List<StatAlarm> newWeekStatAlarmList = new ArrayList<>();

        //遍历范围列表，讲符合条件的数据放入lineList中。
        //根据statType，获取是7/30天的数据。最中获取statType*2前的数据进行计算
        for (StatAlarm statAlarm : list) {
            if (statAlarm == null
                    || statAlarm.getDate() == null
                    || statAlarm.getDate().equals("")
                    || statAlarm.getCompanyId() == null) {
                continue;
            }

            if (compareDate(statAlarm, 14)) {
                if (compareDate(statAlarm, 7)) {
                    newWeekStatAlarmList.add(statAlarm);

                    if (statType == 7) {
                        StatAlarmLineDTO lineDTO = new StatAlarmLineDTO();
                        CommonUtils.copyProperties(statAlarm, lineDTO);
                        statAlarmLineDTOList.add(lineDTO);
                    }
                } else {
                    oldWeekStatAlarmList.add(statAlarm);
                }
            }

            if (compareDate(statAlarm, 60)) {
                if (compareDate(statAlarm, 30)) {
                    newMonthStatAlarmList.add(statAlarm);

                    if (statType == 30) {
                        StatAlarmLineDTO lineDTO = new StatAlarmLineDTO();
                        CommonUtils.copyProperties(statAlarm, lineDTO);
                        statAlarmLineDTOList.add(lineDTO);
                    }
                } else {
                    oldMonthStatAlarmList.add(statAlarm);
                }
            }
        }

        StatAlarmDTO statAlarmDTO = null;

        StatAlarm oldMonthStatAlarm = doStatCount(oldMonthStatAlarmList);
        StatAlarm newMonthStatAlarm = doStatCount(newMonthStatAlarmList);
        StatAlarm oldWeekStatAlarm = doStatCount(oldWeekStatAlarmList);
        StatAlarm newWeekStatAlarm = doStatCount(newWeekStatAlarmList);
        StatAlarm statTypeAlarm = null;
        if (statType == 7) {
            statTypeAlarm = newWeekStatAlarm;
        } else if (statType == 30) {
            statTypeAlarm = newMonthStatAlarm;
        } else {
            List<StatAlarm> todayStatAlarmList = listTodayStatAlarm(companyId);
            if (todayStatAlarmList != null && todayStatAlarmList.size() > 0) {
                statTypeAlarm = doStatCount(list);
                for (StatAlarm statAlarm : todayStatAlarmList) {
                    if (statAlarm != null) {
                        StatAlarmLineDTO lineDTO = new StatAlarmLineDTO();
                        CommonUtils.copyProperties(statAlarm, lineDTO);
                        statAlarmLineDTOList.add(lineDTO);
                    }
                }
            }
        }

        statAlarmDTO = buildStatAlarmDto(oldMonthStatAlarm, newMonthStatAlarm, oldWeekStatAlarm, newWeekStatAlarm, statTypeAlarm);

        setDefault(statAlarmLineDTOList, statType, companyId);
        statAlarmDTO.setList(statAlarmLineDTOList);

        return RestResponse.success(statAlarmDTO);
    }

    static void setDefault(List<StatAlarmLineDTO> statAlarmLineDTOList, Integer statType, Long companyId) {
        if (statAlarmLineDTOList == null) {
            statAlarmLineDTOList = new ArrayList<>();
        }
//        Map<String, StatAlarmLineDTO> map = statAlarmLineDTOList.stream().collect(Collectors.toMap(StatAlarmLineDTO::getDate, stat -> stat));

        Map<String, StatAlarmLineDTO> map = statAlarmLineDTOList.stream().collect(Collectors.toMap(StatAlarmLineDTO::getDate, a -> a, (k1, k2) -> k1));

        if (statType == 30 || statType == 7) {
            for (int i = 1; i <= statType; i++) {
                long time = System.currentTimeMillis() - (DAY_TIME * i);
                String date = DateUtil.format(DateUtil.YEAR_DAY, new Date(time));
                if (!map.containsKey(date)) {
                    statAlarmLineDTOList.add(new StatAlarmLineDTO(date, companyId));
                }
            }
            Collections.sort(statAlarmLineDTOList, (p1, p2) -> p1.getDate().compareTo(p2.getDate()));
        } else {

            Integer hour = 0;
            Integer curr = Integer.parseInt(DateUtil.format(DateUtil.HOUR, new Date()));
            while (hour<=curr){
                if (!map.containsKey(hour.toString()) && !map.containsKey("0"+hour.toString()) ) {
                    statAlarmLineDTOList.add(new StatAlarmLineDTO(hour.toString(), companyId));
                }
                hour++;
            }
            Collections.sort(statAlarmLineDTOList, (p1, p2) -> (Integer.parseInt(p1.getDate()))-(Integer.parseInt(p2.getDate())));
        }
    }

    @Override
    public RestResponse getStatAlarmDetail(StatAlarmParamDto dto) {
        StatAlarmParamDto paramDto = handleStatAlarmDetailParam(dto);
        return alarmStatDetailService.getStatAlarmDetail(paramDto);
    }

    StatAlarmParamDto handleStatAlarmDetailParam(StatAlarmParamDto dto) {
        Date curr = new Date();
        if (dto == null) {
            dto = new StatAlarmParamDto();
        }

//        if (dto.getBeginTime() == null || dto.getEndTime() == null) {
//            dto.setEndTime(curr);
//            Date begin = new Date(DateUtil.getTodayZero().getTime() - MONTH_TIME);
//            dto.setBeginTime(begin);
//        } else if (dto.getEndTime().getTime() - dto.getBeginTime().getTime() > MONTH_TIME) {
//            dto.setBeginTime(new Date(DateUtil.getZero(dto.getEndTime()).getTime() - MONTH_TIME));
//        }

        log.info("企业：{}，开始时间：{}，结束时间：{}", dto.getCompanyId(), DateUtil.format(DateUtil.YEAR_SECOND, dto.getBeginTime()), DateUtil.format(DateUtil.YEAR_SECOND, dto.getEndTime()));
        return dto;
    }


    private List<StatAlarm> listTodayStatAlarm(Long companyId) {

        AlarmInfoReqDto dto = new AlarmInfoReqDto();
        if (companyId != null) {
            dto.setCompanyId(companyId);
        }
        dto.setBeginTime(DateUtil.getTodayZero());
        List<AlarmInfoResDto> alarmList = alarmService.listAlarmInfo(dto);
        if (alarmList == null || alarmList.size() <= 0) {
            return null;
        }

        Map<String, StatAlarm> map = new HashMap<>();
        List<Integer> terminalAlarms = AlarmCodeEnum.getTerminalAlarms();
        for (AlarmInfoResDto alarmDto : alarmList) {
            if (alarmDto == null
                    || alarmDto.getBeginTime() == null
                    || alarmDto.getAlarmCode() == null) {
                continue;
            }

            String key = DateUtil.format("HH", alarmDto.getBeginTime());
            StatAlarm statAlarm = map.get(key);
            statAlarm = buildTodayStatAlarm(statAlarm, alarmDto, terminalAlarms);
            if (statAlarm != null) {
                statAlarm.setDate(key);
                statAlarm.setCompanyId(alarmDto.getCompanyId());
                map.put(key, statAlarm);
            }
        }

        List<StatAlarm> result = new ArrayList<>(map.values());

        return result;
    }


    public StatAlarm buildTodayStatAlarm(StatAlarm statAlarm, AlarmInfoResDto alarmDto, List<Integer> terminalAlarms) {
        StatAlarm res = statAlarm;
        if (res == null) {
            res = new StatAlarm();
        }

        switch (AlarmCodeEnum.getEnum(alarmDto.getAlarmCode())) {
            case IN_FENCE:
                res.setInFenceAlarmCount(res.getInFenceAlarmCount() + 1);
                break;
            case OUT_FENCE:
                res.setOutFenceAlarmCount(res.getOutFenceAlarmCount() + 1);
                break;
            case OFF_LINE:
                res.setOffLineCount(res.getOffLineCount() + 1);
                break;
            case MILEAGE_EXCEPTION_CHANGE:
                res.setMileageExceptionChangeCount(res.getMileageExceptionChangeCount() + 1);
                break;
            default:
                if (terminalAlarms.contains(alarmDto.getAlarmCode())) {
                    switch (AlarmLevelEnum.getEnum(alarmDto.getAlarmLevel())) {
                        case ONE:
                            res.setOneLvAlarmCount(res.getOneLvAlarmCount() + 1);
                            break;
                        case PLATFORM:
                            res.setTwoLvAlarmCount(res.getTwoLvAlarmCount() + 1);
                            break;
                        case THREE:
                            res.setThreeLvAlarmCount(res.getThreeLvAlarmCount() + 1);
                            break;
                        default:
                    }
                } else {
                    res = null;
                }

        }
        return res;
    }

    private StatAlarmDTO buildStatAlarmDto(StatAlarm oldMonth, StatAlarm newMonth, StatAlarm oldWeek, StatAlarm newWeek, StatAlarm statTypeAlarm) {

        if (statTypeAlarm == null) {
            statTypeAlarm = new StatAlarm();
        }

        StatAlarmDTO dto = new StatAlarmDTO();

        Long oldWeekVehicleCount = oldWeek.getVehicleCount();
        Long newWeekVehicleCount = newWeek.getVehicleCount();
        Long oldMonthVehicleCount = oldMonth.getVehicleCount();
        Long newMonthVehicleCount = newMonth.getVehicleCount();


        String inFenceAlarmCodeMsg = AlarmCodeEnum.IN_FENCE.getMsg().replaceAll("报警", "");
        String outFenceAlarmCodeMsg = AlarmCodeEnum.OUT_FENCE.getMsg().replaceAll("报警", "");
        String oneLevelAlarmMsg = AlarmLevelEnum.ONE.getMsg().replaceAll("报警", "");
        String twoLevelAlarmMsg = AlarmLevelEnum.PLATFORM.getMsg().replaceAll("报警", "");
        String threeLevelAlarmMsg = AlarmLevelEnum.THREE.getMsg().replaceAll("报警", "");
        String offLineAlarmCodeMsg = AlarmCodeEnum.OFF_LINE.getMsg().replaceAll("报警", "");
        String mileageExceptionChangeAlarmCodeMsg = AlarmCodeEnum.MILEAGE_EXCEPTION_CHANGE.getMsg().replaceAll("报警", "");


        //构建围栏报警周环比列表
        List<StatAlarmRatioDTO> weekFenceRatioList = new ArrayList<>();
        StatAlarmRatioDTO weekInFenceRatioDTO = new StatAlarmRatioDTO();
        weekInFenceRatioDTO.setCount(newWeek.getInFenceAlarmCount());
        weekInFenceRatioDTO.setRatio(getSameComparedRatio(oldWeekVehicleCount, oldWeek.getInFenceAlarmCount(), newWeekVehicleCount, newWeek.getInFenceAlarmCount()));
        weekInFenceRatioDTO.setType(inFenceAlarmCodeMsg);
        weekFenceRatioList.add(weekInFenceRatioDTO);
        StatAlarmRatioDTO weekOutFenceRatioDTO = new StatAlarmRatioDTO();
        weekOutFenceRatioDTO.setCount(newWeek.getOutFenceAlarmCount());
        weekOutFenceRatioDTO.setRatio(getSameComparedRatio(oldWeekVehicleCount, oldWeek.getOutFenceAlarmCount(), newWeekVehicleCount, newWeek.getOutFenceAlarmCount()));
        weekOutFenceRatioDTO.setType(outFenceAlarmCodeMsg);
        weekFenceRatioList.add(weekOutFenceRatioDTO);
        dto.setWeekFenceRatioList(weekFenceRatioList);

        //构建围栏报警月环比列表
        List<StatAlarmRatioDTO> monthRatioList = new ArrayList<>();
        StatAlarmRatioDTO monthInFenceRatioDTO = new StatAlarmRatioDTO();
        monthInFenceRatioDTO.setCount(newMonth.getInFenceAlarmCount());
        monthInFenceRatioDTO.setRatio(getSameComparedRatio(oldMonthVehicleCount, oldMonth.getInFenceAlarmCount(), newMonthVehicleCount, newMonth.getInFenceAlarmCount()));
        monthInFenceRatioDTO.setType(inFenceAlarmCodeMsg);
        monthRatioList.add(monthInFenceRatioDTO);
        StatAlarmRatioDTO monthOutFenceRatioDTO = new StatAlarmRatioDTO();
        monthOutFenceRatioDTO.setCount(newMonth.getOutFenceAlarmCount());
        monthOutFenceRatioDTO.setRatio(getSameComparedRatio(oldMonthVehicleCount, oldMonth.getOutFenceAlarmCount(), newMonthVehicleCount, newMonth.getOutFenceAlarmCount()));
        monthOutFenceRatioDTO.setType(outFenceAlarmCodeMsg);
        monthRatioList.add(monthOutFenceRatioDTO);
        dto.setMonthFenceRatioList(monthRatioList);

        //构建报警等级周环比列表
        StatAlarmRatioDTO weekOneLvAlarmRatioDTO = new StatAlarmRatioDTO();
        weekOneLvAlarmRatioDTO.setRatio(getSameComparedRatio(oldWeekVehicleCount, oldWeek.getOneLvAlarmCount(), newWeekVehicleCount, newWeek.getOneLvAlarmCount()));
        weekOneLvAlarmRatioDTO.setCount(newWeek.getOneLvAlarmCount());
        weekOneLvAlarmRatioDTO.setType(oneLevelAlarmMsg);
        StatAlarmRatioDTO weekTwoLvAlarmRatioDTO = new StatAlarmRatioDTO();
        weekTwoLvAlarmRatioDTO.setRatio(getSameComparedRatio(oldWeekVehicleCount, oldWeek.getTwoLvAlarmCount(), newWeekVehicleCount, newWeek.getTwoLvAlarmCount()));
        weekTwoLvAlarmRatioDTO.setCount(newWeek.getTwoLvAlarmCount());
        weekTwoLvAlarmRatioDTO.setType(twoLevelAlarmMsg);
        StatAlarmRatioDTO weekThreeLvAlarmRatioDTO = new StatAlarmRatioDTO();
        weekThreeLvAlarmRatioDTO.setRatio(getSameComparedRatio(oldWeekVehicleCount, oldWeek.getThreeLvAlarmCount(), newWeekVehicleCount, newWeek.getThreeLvAlarmCount()));
        weekThreeLvAlarmRatioDTO.setCount(newWeek.getThreeLvAlarmCount());
        weekThreeLvAlarmRatioDTO.setType(threeLevelAlarmMsg);
        List<StatAlarmRatioDTO> weekLevelRatioList = new ArrayList<>();
        weekLevelRatioList.add(weekOneLvAlarmRatioDTO);
        weekLevelRatioList.add(weekTwoLvAlarmRatioDTO);
        weekLevelRatioList.add(weekThreeLvAlarmRatioDTO);
        dto.setWeekLevelRatioList(weekLevelRatioList);

        //构建报警等级月环比列表
        StatAlarmRatioDTO monthOneLvAlarmRatioDTO = new StatAlarmRatioDTO();
        monthOneLvAlarmRatioDTO.setRatio(getSameComparedRatio(oldMonthVehicleCount, oldMonth.getOneLvAlarmCount(), newMonthVehicleCount, newMonth.getOneLvAlarmCount()));
        monthOneLvAlarmRatioDTO.setCount(newMonth.getOneLvAlarmCount());
        monthOneLvAlarmRatioDTO.setType(oneLevelAlarmMsg);
        StatAlarmRatioDTO monthTwoLvAlarmRatioDTO = new StatAlarmRatioDTO();
        monthTwoLvAlarmRatioDTO.setRatio(getSameComparedRatio(oldMonthVehicleCount, oldMonth.getTwoLvAlarmCount(), newMonthVehicleCount, newMonth.getTwoLvAlarmCount()));
        monthTwoLvAlarmRatioDTO.setCount(newMonth.getTwoLvAlarmCount());
        monthTwoLvAlarmRatioDTO.setType(twoLevelAlarmMsg);
        StatAlarmRatioDTO monthThreeLvAlarmRatioDTO = new StatAlarmRatioDTO();
        monthThreeLvAlarmRatioDTO.setRatio(getSameComparedRatio(oldMonthVehicleCount, oldMonth.getThreeLvAlarmCount(), newMonthVehicleCount, newMonth.getThreeLvAlarmCount()));
        monthThreeLvAlarmRatioDTO.setCount(newMonth.getThreeLvAlarmCount());
        monthThreeLvAlarmRatioDTO.setType(threeLevelAlarmMsg);
        List<StatAlarmRatioDTO> monthLevelRatioList = new ArrayList<>();
        monthLevelRatioList.add(monthOneLvAlarmRatioDTO);
        monthLevelRatioList.add(monthTwoLvAlarmRatioDTO);
        monthLevelRatioList.add(monthThreeLvAlarmRatioDTO);
        dto.setMonthLevelRatioList(monthLevelRatioList);

        //构建风险报警周环比列表
        List<StatAlarmRatioDTO> weekRiskRatioList = new ArrayList<>();
        StatAlarmRatioDTO weekOffLineAlarmRatioDTO = new StatAlarmRatioDTO();
        weekOffLineAlarmRatioDTO.setCount(newWeek.getOffLineCount());
        weekOffLineAlarmRatioDTO.setType(offLineAlarmCodeMsg);
        weekOffLineAlarmRatioDTO.setRatio(getSameComparedRatio(oldWeekVehicleCount, oldWeek.getOffLineCount(), newWeekVehicleCount, newWeek.getOffLineCount()));
        StatAlarmRatioDTO weekMileageExceptionChangeAlarmRatioDTO = new StatAlarmRatioDTO();
        weekMileageExceptionChangeAlarmRatioDTO.setCount(newWeek.getMileageExceptionChangeCount());
        weekMileageExceptionChangeAlarmRatioDTO.setType(mileageExceptionChangeAlarmCodeMsg);
        weekMileageExceptionChangeAlarmRatioDTO.setRatio(getSameComparedRatio(oldWeekVehicleCount, oldWeek.getMileageExceptionChangeCount(), newWeekVehicleCount, newWeek.getMileageExceptionChangeCount()));
        weekRiskRatioList.add(weekOffLineAlarmRatioDTO);
        weekRiskRatioList.add(weekMileageExceptionChangeAlarmRatioDTO);
        dto.setWeekRiskRatioList(weekRiskRatioList);

        //构建风险报警月环比列表
        List<StatAlarmRatioDTO> monthRiskRatioList = new ArrayList<>();
        StatAlarmRatioDTO monthOffLineAlarmRatioDTO = new StatAlarmRatioDTO();
        monthOffLineAlarmRatioDTO.setType(offLineAlarmCodeMsg);
        monthOffLineAlarmRatioDTO.setCount(newMonth.getOffLineCount());
        monthOffLineAlarmRatioDTO.setRatio(getSameComparedRatio(oldMonthVehicleCount, oldMonth.getOffLineCount(), newMonthVehicleCount, oldMonth.getOffLineCount()));
        StatAlarmRatioDTO monthMileageExceptionChangeAlarmRatioDTO = new StatAlarmRatioDTO();
        monthMileageExceptionChangeAlarmRatioDTO.setRatio(getSameComparedRatio(oldMonthVehicleCount, oldMonth.getMileageExceptionChangeCount(), newMonthVehicleCount, oldMonth.getMileageExceptionChangeCount()));
        monthMileageExceptionChangeAlarmRatioDTO.setCount(newMonth.getMileageExceptionChangeCount());
        monthMileageExceptionChangeAlarmRatioDTO.setType(mileageExceptionChangeAlarmCodeMsg);
        monthRiskRatioList.add(monthOffLineAlarmRatioDTO);
        monthRiskRatioList.add(monthMileageExceptionChangeAlarmRatioDTO);
        dto.setMonthRiskRatioList(monthRiskRatioList);


        //通过  “进围栏报警数”  和  “进出围栏之和” 获得 “进围栏报警占比”
        Long fenceAlarmCount = (statTypeAlarm.getInFenceAlarmCount() + statTypeAlarm.getOutFenceAlarmCount());
        List<StatAlarmRatioDTO> fenceRatioList = new ArrayList<>();
        StatAlarmRatioDTO outFenceRatioDTO = new StatAlarmRatioDTO();
        outFenceRatioDTO.setRatio(getRatio(statTypeAlarm.getOutFenceAlarmCount(), fenceAlarmCount));
        outFenceRatioDTO.setCount(statTypeAlarm.getOutFenceAlarmCount());
        outFenceRatioDTO.setType(outFenceAlarmCodeMsg);
        StatAlarmRatioDTO inFenceRatioDTO = new StatAlarmRatioDTO();
        inFenceRatioDTO.setRatio(getRatio(statTypeAlarm.getInFenceAlarmCount(), fenceAlarmCount));
        inFenceRatioDTO.setCount(statTypeAlarm.getInFenceAlarmCount());
        inFenceRatioDTO.setType(inFenceAlarmCodeMsg);
        fenceRatioList.add(outFenceRatioDTO);
        fenceRatioList.add(inFenceRatioDTO);
        dto.setFenceRatioList(fenceRatioList);

        //等级饼状图
        Long levelAlarmCount = (statTypeAlarm.getTwoLvAlarmCount() + statTypeAlarm.getThreeLvAlarmCount() + statTypeAlarm.getOneLvAlarmCount());
        List<StatAlarmRatioDTO> levelRatioList = new ArrayList<>();
        StatAlarmRatioDTO oneLvAlarmRatioDTO = new StatAlarmRatioDTO();
        oneLvAlarmRatioDTO.setRatio(getRatio(statTypeAlarm.getOneLvAlarmCount(), levelAlarmCount));
        oneLvAlarmRatioDTO.setCount(statTypeAlarm.getOneLvAlarmCount());
        oneLvAlarmRatioDTO.setType(oneLevelAlarmMsg);

        StatAlarmRatioDTO twoLvAlarmRatioDTO = new StatAlarmRatioDTO();
        twoLvAlarmRatioDTO.setType(twoLevelAlarmMsg);
        twoLvAlarmRatioDTO.setCount(statTypeAlarm.getTwoLvAlarmCount());
        twoLvAlarmRatioDTO.setRatio(getRatio(statTypeAlarm.getTwoLvAlarmCount(), levelAlarmCount));
        StatAlarmRatioDTO threeLvAlarmRatioDTO = new StatAlarmRatioDTO();
        threeLvAlarmRatioDTO.setType(threeLevelAlarmMsg);
        threeLvAlarmRatioDTO.setRatio(getRatio(statTypeAlarm.getThreeLvAlarmCount(), levelAlarmCount));
        threeLvAlarmRatioDTO.setCount(statTypeAlarm.getThreeLvAlarmCount());
        levelRatioList.add(oneLvAlarmRatioDTO);
        levelRatioList.add(twoLvAlarmRatioDTO);
        levelRatioList.add(threeLvAlarmRatioDTO);
        dto.setLevelRatioList(levelRatioList);


        Long riskAlarmCount = statTypeAlarm.getOffLineCount() + statTypeAlarm.getMileageExceptionChangeCount();
        List<StatAlarmRatioDTO> riskRatioList = new ArrayList<>();
        StatAlarmRatioDTO offLineAlarmRatioDTO = new StatAlarmRatioDTO();
        offLineAlarmRatioDTO.setCount(statTypeAlarm.getOffLineCount());
        offLineAlarmRatioDTO.setRatio(getRatio(statTypeAlarm.getOffLineCount(), riskAlarmCount));
        offLineAlarmRatioDTO.setType(offLineAlarmCodeMsg);
        StatAlarmRatioDTO mileageExceptionChangeAlarmRatioDTO = new StatAlarmRatioDTO();
        mileageExceptionChangeAlarmRatioDTO.setType(mileageExceptionChangeAlarmCodeMsg);
        mileageExceptionChangeAlarmRatioDTO.setCount(statTypeAlarm.getMileageExceptionChangeCount());
        mileageExceptionChangeAlarmRatioDTO.setRatio(getRatio(statTypeAlarm.getMileageExceptionChangeCount(), riskAlarmCount));
        riskRatioList.add(offLineAlarmRatioDTO);
        riskRatioList.add(mileageExceptionChangeAlarmRatioDTO);
        dto.setRiskRatioList(riskRatioList);

        return dto;
    }

    public static void main(String[] args) {
        getSameComparedRatio(100L,31L,100L,49L);
    }

    private static String getSameComparedRatio(Long oldVehicleCount, Long oldAlarmCount, Long newVehicleCount, Long newAlarmCount) {
        //(A1/A-B1/B)*100%F
        if (oldAlarmCount != null
                && oldVehicleCount != null
                && newAlarmCount != null
                && newVehicleCount != null
                && newVehicleCount != 0
                && oldVehicleCount != 0) {
            Double newRatio = (Double.valueOf(newAlarmCount) / Double.valueOf(newVehicleCount));
            Double oldRatio = (Double.valueOf(oldAlarmCount) / Double.valueOf(oldVehicleCount));
            Double ratio = Double.valueOf( newRatio - oldRatio ) * 100;
//            log.info("newAlarmCount:{},newVehicleCount:{},oldAlarmCount:{},oldVehicleCount:{}", newAlarmCount, newVehicleCount, oldAlarmCount, oldVehicleCount);
            BigDecimal bg = new BigDecimal(ratio);
            String f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
            return f1 + "%";
        }
        return "0%";
    }

    private String getRatio(Long numerator, Long denominator) {
        if (numerator != null && denominator != null && denominator != 0) {
            Double f1 = Double.valueOf(numerator) / Double.valueOf(denominator) * 100;
            String res = new BigDecimal(f1).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
            return res + "%";
        }
        return "0%";
    }

    private StatAlarm doStatCount(List<StatAlarm> list) {
        StatAlarm res = new StatAlarm();
        Long companyId = null;

        Long outFenceAlarmCount = 0L;
        Long inFenceAlarmCount = 0L;
        Long oneLvAlarmCount = 0L;
        Long twoLvAlarmCount = 0L;
        Long threeLvAlarmCount = 0L;
        Long offLineCount = 0L;
        Long mileageExceptionChangeCount = 0L;
        Long vehicleCount = 0L;
        for (StatAlarm statAlarm : list) {
            if (statAlarm != null) {
                inFenceAlarmCount += (statAlarm.getInFenceAlarmCount() == null ? 0 : statAlarm.getInFenceAlarmCount());
                outFenceAlarmCount += (statAlarm.getOutFenceAlarmCount() == null ? 0 : statAlarm.getOutFenceAlarmCount());
                oneLvAlarmCount += (statAlarm.getOneLvAlarmCount() == null ? 0 : statAlarm.getOneLvAlarmCount());
                twoLvAlarmCount += (statAlarm.getTwoLvAlarmCount() == null ? 0 : statAlarm.getTwoLvAlarmCount());
                threeLvAlarmCount += (statAlarm.getThreeLvAlarmCount() == null ? 0 : statAlarm.getThreeLvAlarmCount());
                offLineCount += (statAlarm.getOffLineCount() == null ? 0 : statAlarm.getOffLineCount());
                mileageExceptionChangeCount += (statAlarm.getMileageExceptionChangeCount() == null ? 0 : statAlarm.getMileageExceptionChangeCount());
                vehicleCount += (statAlarm.getVehicleCount() == null ? 0 : statAlarm.getVehicleCount());
                if (companyId == null && statAlarm.getCompanyId() != null) {
                    companyId = statAlarm.getCompanyId();
                }
            }
        }

        res.setCompanyId(companyId);
        res.setVehicleCount(vehicleCount);
        res.setInFenceAlarmCount(inFenceAlarmCount);
        res.setOutFenceAlarmCount(outFenceAlarmCount);
        res.setOneLvAlarmCount(oneLvAlarmCount);
        res.setTwoLvAlarmCount(twoLvAlarmCount);
        res.setThreeLvAlarmCount(threeLvAlarmCount);
        res.setOffLineCount(offLineCount);
        res.setMileageExceptionChangeCount(mileageExceptionChangeCount);
        return res;
    }

    private static boolean compareDate(StatAlarm statAlarm, Integer statType) {
        Date statDate = null;
        try {
//            log.info("比较时间：  statAlarm:{}",statAlarm);
            if (statAlarm == null || statAlarm.getDate()==null || ("").equals(statAlarm.getDate())) {
                log.error("参数错误，时间为null，statAlarm ** {}", statAlarm);
                return false;
            }

            SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.YEAR_DAY);
            statDate = sdf.parse(statAlarm.getDate());
//            statDate = DateUtil.parser(DateUtil.YEAR_DAY, statAlarm.getDate());
            Date date = DateUtil.subDay(new Date(), statType + 1);
            return statDate.getTime() >= date.getTime();
        } catch (ParseException e) {
            log.error("比较异常  statAlarm:{},statType:{}",statAlarm,statType);
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 首页离线报警
     *
     * @return
     */
    @Override
    public Map<String, Long> getAlarmCount(Long companyId) {

        //获取围栏报警
        List<Integer> alarmCodes = Arrays.asList(AlarmCodeEnum.OUT_FENCE.getFlag(), AlarmCodeEnum.IN_FENCE.getFlag());
        Long fenceAlarmCount = alarmService.getAlarmCountByAlarmCodes(alarmCodes, companyId);

        //获取设备报警
        alarmCodes = AlarmCodeEnum.getTerminalAlarms();
        Long deviceAlarmCount = alarmService.getAlarmCountByAlarmCodes(alarmCodes, companyId);

        //获取离线报警
        alarmCodes = Arrays.asList(AlarmCodeEnum.OFF_LINE.getFlag());
        Long offLineAlarmCount = alarmService.getAlarmCountByAlarmCodes(alarmCodes, companyId);

        Map<String, Long> map = new HashMap<>();
        map.put("fenceAlarmCount", fenceAlarmCount);
        map.put("deviceAlarmCount", deviceAlarmCount);
        map.put("offLineAlarmCount", offLineAlarmCount);
        return map;
    }

}
